
/*
 * @项目名称: 模板开发
 * @FilePath: /meek/src/renderer/render/linerender.js
 * @Author: 
 * @Date: 2017-03-23T11:12:12+08:00
 * @LastEditors: kongxueyang@datatang.com
 * @LastEditTime: 2021-01-15T14:36:55+08:00
 * Copyright (c) 2018-2022
 */

/**
 * Created by zhangyong on 2017/3/20.
 */
import GeometryRender from '../render/geomertyrender'
import LineStyle from '../../style/linestyle'

import {colorToString} from '../../utils/helpers'
import {Transform} from '../../data/matrix/transform'
import {
  drawPoint,
  drawPointIndexes
} from './drawPoint';

import BezierRender from './bezierrender';

export default class LineRender extends GeometryRender {

  constructor (context) {
    super(context)
  }

  /**
   *
   * @param feature
   * @param renderStyle
   * @param transform
   */
  render (feature, renderStyle, transform) {
    if (!feature) {
      return
    }

    const ctx = this.context
    const styleArray = renderStyle
    const geometry = feature.geometry

    const transform2D =  Transform.transform2D
    let coordinates = []
    let renderCoords = [];
    // TODO find a way to cache the rendered data
    if (this._pixelCoordinates &&
        this.equalsTransform(transform, this.renderedTransform)) {
      coordinates = this._pixelCoordinates
      // console.log('get the rendered data from chche for line')
    } else {
      const geometryCoordinates = geometry.getCoordinates()

      geometryCoordinates.forEach(function(points){
        let coordinate = transform2D(
          points, 0, points.length, 2,
          transform)

        coordinate[0] = (coordinate[0] + 0.5 ) | 0
        coordinate[1] = (coordinate[1] + 0.5 ) | 0

        coordinates.push(coordinate)
      })

      this._pixelCoordinates = coordinates
      Transform.setFromArray(this.renderedTransform, transform)
      // console.log('caclulate the rendered data for line')
    }
    renderCoords[0] =coordinates;

    const len = styleArray.length
    for(let i = 0; i < len ; i ++){
      let styleObj = styleArray[i]

      let renderOptions = {
        coordinates: coordinates,
        width: styleObj.width,
        strokeStyle: colorToString(styleObj.color,styleObj.alpha),
        lineCap: styleObj.lineCap,
        lineJion: styleObj.lineJion,
        miterLimit: styleObj.miterLimit,
        style: styleObj.style,
        transform: transform
        //hasDash: styleObj.style === LineStyle.DASH ? true : false
      }
      drawPoint(ctx, renderCoords, feature, styleArray)
      this.drawLine(ctx, renderOptions, feature)
      this.drawPointIndexes(ctx, renderOptions, feature);
    }

    this.drawBezier(feature, renderStyle, transform);
  }

  drawLine (ctx, renderOpt, feature) {
    ctx.save()
    ctx.strokeStyle = renderOpt.strokeStyle
    ctx.lineWidth = renderOpt.width

    ctx.lineCap = renderOpt.lineCap
    ctx.lineJoin = renderOpt.lineJion
    ctx.miterLimit = renderOpt.miterLimit


    const coordinates = renderOpt.coordinates;
    if (renderOpt.style === LineStyle.DASH) {
      ctx.setLineDash([5, 5])
    } else if (renderOpt.style === LineStyle.DASHDOT) {
      ctx.setLineDash([10, 3, 3, 3]);
    }
    let beforeLineDash = ctx.getLineDash();
    let virtualLines = [];
    for (let i = 0,ii = coordinates.length ; i < ii - 1 ; i++) {
      ctx.beginPath()
      const bezierStart = feature.geometry.isBezierStart(i);
      if (bezierStart) {
        // ctx.setLineDash([5, 5]);
        const transform2D = Transform.transform2D;
        const points = bezierStart.points.map(item => {
          return transform2D(item, 0, item.length, 2, renderOpt.transform);
        })

        virtualLines.push([
          [coordinates[i][0], coordinates[i][1]],
          ...points,
          [coordinates[i + 1][0], coordinates[i + 1][1]]
        ])
        continue;
      } else {
        ctx.setLineDash(beforeLineDash);
        ctx.strokeStyle =  renderOpt.strokeStyle;
      }
      ctx.moveTo(coordinates[i][0],coordinates[i][1])
      ctx.lineTo(coordinates[i + 1][0],coordinates[i + 1][1])
      ctx.stroke()

      ctx.closePath()
    }


    //添加贝塞尔黄色虚线
    const color = ctx.strokeStyle;
    virtualLines.forEach((item, index) => {
      if (feature.styleHighLight) {
        ctx.beginPath();
        ctx.strokeStyle = color;
        ctx.setLineDash([5, 5])
        item.forEach((point, index) => {
          if (index == 0) {
            ctx.moveTo(...point);
          }
          ctx.lineTo(...point);
        })
        ctx.stroke();
      }
      ctx.beginPath();
      ctx.strokeStyle = '#FFFF00';
      ctx.setLineDash([5, 5])
      ctx.lineWidth = 1;
      ctx.moveTo(...item[0]);
      ctx.lineTo(...item[item.length - 1]);
      ctx.stroke();
    })




    ctx.restore()
  }


  drawBezier(feature, renderStyle, transform) {
    let bezierdata = feature.geometry.bezier;
    const ctx = this.context
    if (bezierdata && bezierdata.length) {
      const geometry = feature.geometry;
      const transform2D =  Transform.transform2D
      bezierdata.forEach(item => {
        let { renderPoints } = geometry.getBezierItem(item);
        let transformCoords = [];
        renderPoints.forEach(function(points){
          let coordinate = transform2D(
            points, 0, points.length, 2,
            transform)

          coordinate[0] = (coordinate[0] + 0.5 ) | 0
          coordinate[1] = (coordinate[1] + 0.5 ) | 0

          transformCoords.push(coordinate)
        })

        const styleArray = renderStyle;

        styleArray.forEach(styleObj => {
          let renderOptions = {
            coordinates: transformCoords,
            width: styleObj.width,
            strokeStyle: colorToString(styleObj.color,styleObj.alpha),
            lineCap: styleObj.lineCap,
            lineJion: styleObj.lineJion,
            miterLimit: styleObj.miterLimit,
            style: styleObj.style
          }

          BezierRender.drawBezier(ctx, renderOptions);
          if (feature.styleHighLight) {
            BezierRender.drawPoint(ctx, {
              coordinates: transformCoords.slice(1, transformCoords.length - 1)
            }, feature)
          }

        })
      })
    }
  }

  drawPointIndexes(ctx, renderOpt, feature) {
    if (!feature.showPointIndex) {
      return ;
    }

    const coordinates = renderOpt.coordinates
    drawPointIndexes(ctx, coordinates);
  }
}
